#ifndef __COMMANDPROCESS_H__
#define __COMMANDPROCESS_H__

#include <wx/wx.h>
#include "USBCommunication.h"
#include "panel_reverb.h"
#include "panel_chorus.h"
#include "panel_delay.h"
#include "panel_distortion.h"
#include "panel_compressor.h"
#include "panel_equalizer.h"
#include "panel_wah.h"
#include "panel_preset.h"


#define CMD_INDEX_SYSTEM                0x01
#define SYSTEM_PARAM_INDEX_INFO         0x00

#define CMD_INDEX_EFFECT_REVERB         0x11
#define CMD_INDEX_EFFECT_REVERB_MIC     0x12
#define CMD_INDEX_EFFECT_DELAY          0x13
#define CMD_INDEX_EFFECT_EQ             0x14
#define CMD_INDEX_EFFECT_PRESET         0x15
#define CMD_INDEX_EFFECT_CHORUS         0x16
#define CMD_INDEX_EFFECT_COMPRESSOR     0x17
#define CMD_INDEX_EFFECT_DISTORTION     0x18
#define CMD_INDEX_EFFECT_IR				0x19
#define CMD_INDEX_EFFECT_WAH            0x1A
#define CMD_INDEX_VOLUME                0x40


#define EFFECT_PARAM_INDEX_REVERB           0
#define EFFECT_PARAM_INDEX_REVERB_ENABLE    1
#define EFFECT_PARAM_INDEX_REVERB_DRY       2
#define EFFECT_PARAM_INDEX_REVERB_WET       3
#define EFFECT_PARAM_INDEX_REVERB_DAMP      4
#define EFFECT_PARAM_INDEX_REVERB_TONE      5
#define EFFECT_PARAM_INDEX_REVERB_FEEDBACK  6

#define EFFECT_PARAM_INDEX_CHORUS           0
#define EFFECT_PARAM_INDEX_CHORUS_ENABLE    1
#define EFFECT_PARAM_INDEX_CHORUS_DRY       2
#define EFFECT_PARAM_INDEX_CHORUS_WET       3
#define EFFECT_PARAM_INDEX_CHORUS_PITCH     4
#define EFFECT_PARAM_INDEX_CHORUS_RATE      5
#define EFFECT_PARAM_INDEX_CHORUS_TONE      6

#define EFFECT_PARAM_INDEX_DELAY            0
#define EFFECT_PARAM_INDEX_DELAY_ENABLE     1
#define EFFECT_PARAM_INDEX_DELAY_TIME       2
#define EFFECT_PARAM_INDEX_DELAY_TONE       3
#define EFFECT_PARAM_INDEX_DELAY_WET        4
#define EFFECT_PARAM_INDEX_DELAY_FEEDBACK   5

#define EFFECT_PARAM_INDEX_DISTORTION              0
#define EFFECT_PARAM_INDEX_DISTORTION_ENABLE       1
#define EFFECT_PARAM_INDEX_DISTORTION_DRIVE        2
#define EFFECT_PARAM_INDEX_DISTORTION_GAIN_INPUT   3
#define EFFECT_PARAM_INDEX_DISTORTION_GAIN_OUTPUT  4
#define EFFECT_PARAM_INDEX_DISTORTION_TONE         5
#define EFFECT_PARAM_INDEX_DISTORTION_FREQ          6
#define EFFECT_PARAM_INDEX_DISTORTION_WIDGET        7
#define EFFECT_PARAM_INDEX_DISTORTION_EQ        8

#define EFFECT_PARAM_INDEX_WAH                      0
#define EFFECT_PARAM_INDEX_WAH_ENABLE               1
#define EFFECT_PARAM_INDEX_WAH_SPEED                2
#define EFFECT_PARAM_INDEX_WAH_FILTER_FREQ_CENTER    3
#define EFFECT_PARAM_INDEX_WAH_FILTER_FREQ_WIDTH      4
#define EFFECT_PARAM_INDEX_WAH_FILTER_GAIN          5
#define EFFECT_PARAM_INDEX_WAH_FILTER_Q             6

#define EFFECT_PARAM_INDEX_COMPRESSOR                      0
#define EFFECT_PARAM_INDEX_COMPRESSOR_ENABLE                1
#define EFFECT_PARAM_INDEX_COMPRESSOR_THRESHOLD							2
#define EFFECT_PARAM_INDEX_COMPRESSOR_RATIO                 3
#define EFFECT_PARAM_INDEX_COMPRESSOR_ATTACK_TIME           4
#define EFFECT_PARAM_INDEX_COMPRESSOR_RELEASE_TIME          5
#define EFFECT_PARAM_INDEX_COMPRESSOR_POSTGAIN              6


#define EFFECT_PARAM_INDEX_PRESET_SAVE      0
#define EFFECT_PARAM_INDEX_PRESET_CHANGE    1
#define EFFECT_PARAM_INDEX_PRESET_SET_GROUP 2


#define MAX_PRESET_NUM 100

#define PARAM_FLOAT_MUL (100.0)

class CommandProcess : public wxEvtHandler
{
public:
    typedef enum
    {
        SUCCESS = 0,
        TIMEOUT,
        FAIL,
        TOLONG
    }Status;
    // typedef enum{
    //     CMD_INDEX_SYSTEM = 0x01,
    //     CMD_INDEX_EFFECT_REVERB,
    //     CMD_INDEX_EFFECT_REVERB_MIC,
    //     CMD_INDEX_EFFECT_DELAY,
    //     CMD_INDEX_EFFECT_EQ,
    //     CMD_INDEX_EFFECT_PRESET,
    //     CMD_INDEX_EFFECT_CHORUS,
    //     CMD_INDEX_EFFECT_COMPRESS,
    //     CMD_INDEX_EFFECT_DISTORTION,
    //     CMD_INDEX_EFFECT_IR,
    //     CMD_INDEX_VOLUME,

    // }COMMAND_INDEX;
    typedef struct
    {
        unsigned char hw_ver;
        unsigned char fw_ver_major;
        unsigned char fw_ver_minor;
        unsigned char name[64];
    }t_dev_info;

public:
    explicit CommandProcess(USBCommunication *_usb_comm = nullptr,char interface_num = 0, unsigned char in_ep = 0, unsigned char out_ep = 0);
    ~CommandProcess();

private:
    // typedef int (*write_data_callback)(const char *data,int len);
    // typedef int (*read_data_callback)(char *data,int len);
    USBCommunication *usb_comm;
    char usb_interface_num;
    unsigned char usb_in_ep;
    unsigned char usb_out_ep;

    int cmd_pack_max_len;
    // int current_preset_num;

    t_dev_info param_struct_dev_info;
    PanelReverb::param_struct param_struct_reverb;
    PanelDelay::param_struct param_struct_delay;
    PanelWah::param_struct param_struct_wah;
    PanelChorus::param_struct param_struct_chorus;
    PanelDistortion::param_struct param_struct_distortion;
    PanelPreset::param_struct param_struct_preset;
    PanelCompressor::param_struct param_struct_cmp;

    Status WriteData(const char *data,int len);
    Status ReadData(char *data,int *actual_length);
    unsigned char data_packet_analyze(const char *buff ,int len);
    unsigned char command_data_analyze(const char *data,int len);
    int create_command_packet(const char *data, int bytes,char *out_packet_buff);

    Status send_get_param_command_data(int preset_num,uint8_t cmd,uint8_t param_index,uint8_t *data,int len);

public:
    void OnReverbParamChange(MyEventReverb &event);
    void OnChorusParamChange(MyEventChorus &event);
    void OnDelayParamChange(MyEventDelay &event);
    void OnWahParamChange(MyEventWah &event);
    void OnDistortionParamChange(MyEventDistortion &event);
    void OnCompressorParamChange(MyEventCompressor &event);
    void OnEqualizerParamChange(MyEventEqualizer &event);
    void OnPresetParamChange(MyEventPreset &event);

    Status get_device_info(t_dev_info &info);
    Status get_param_reverb(int preset_num,PanelReverb::param_struct &param);
    Status get_param_chorus(int preset_num,PanelChorus::param_struct &param);
    Status get_param_delay(int preset_num,PanelDelay::param_struct &param);
    Status get_param_wah(int preset_num,PanelWah::param_struct &param);
    Status get_param_compressor(int preset_num,PanelCompressor::param_struct &param);
    Status get_param_distortion(int preset_num,PanelDistortion::param_struct &param);
    Status get_param_distortion_eq(int preset_num,int band, PanelDistortion::param_struct &param);

    Status set_param_reverb(int preset_num,PanelReverb::param_struct &param);
    Status set_param_reverb_enable(int preset_num,bool enable);
    Status set_param_reverb_dry(int preset_num,double dry);
    Status set_param_reverb_wet(int preset_num,double wet);
    Status set_param_reverb_tone(int preset_num,double tone);
    Status set_param_reverb_damp(int preset_num,double damp);
    Status set_param_reverb_feedback(int preset_num,double feedback);
    Status set_param_chorus(int preset_num,PanelChorus::param_struct &param);
    Status set_param_chorus_enable(int preset_num,bool enable);
    Status set_param_chorus_wet(int preset_num,double wet);
    Status set_param_chorus_dry(int pareset_num,double dry);
    Status set_param_chorus_pitch(int preset_num,double pitch);
    Status set_param_chorus_rate(int preset_num,double rate);
    Status set_param_chorus_tone(int preset_num,double tone);
    Status set_param_delay(int preset_num,PanelDelay::param_struct &param);
    Status set_param_delay_enable(int preset_num,bool enable);
    Status set_param_delay_time(int preset_num,double time_ms);
    Status set_param_delay_tone(int preset_num,double tone);
    Status set_param_delay_feedback(int preset_num,double feedback);
    Status set_param_delay_wet(int preset_num,double wet);
    Status set_param_wah(int preset_num,PanelWah::param_struct &param);
    Status set_param_wah_enable(int preset_num,bool enable);
    Status set_param_wah_speed(int preset_num,double speed);
    Status set_param_wah_filter_q(int preset_num,double filter_q);
    Status set_param_wah_filter_gain(int preset_num,double filter_gain);
    Status set_param_wah_filter_freq_center(int preset_num,double filter_freq_center);
    Status set_param_wah_filter_freq_width(int preset_num,double filter_freq_width);
    Status set_param_compressor(int preset_num,PanelCompressor::param_struct &param);
    Status set_param_compressor_enable(int preset_num,bool enable);
    Status set_param_compressor_threshold(int preset_num,double threshold);
    Status set_param_compressor_ratio(int preset_num,double ratio);
    Status set_param_compressor_attack_time(int preset_num,double attack_time);
    Status set_param_compressor_release_time(int preset_num,double release_time);
    Status set_param_compressor_postgain(int preset_num,double postgain);
    Status set_param_distortion(int preset_num,PanelDistortion::param_struct &param);
    Status set_param_distortion_enable(int preset_num,bool enable);
    Status set_param_distortion_gain_input(int preset_num,double gain);
    Status set_param_distortion_gain_output(int preset_num,double gain);
    Status set_param_distortion_drive(int preset_num,double drive);
    Status set_param_distortion_tone(int preset_num,double tone);
    Status set_param_distortion_freq(int preset_num,double freq);
    Status set_param_distortion_width(int preset_num,double width);
    Status set_param_distortion_eq(int preset_num,int band,FilterParam &eq_param);
    Status set_param_preset_index(int preset_num);
    Status set_param_preset_group(int preset_num,uint32_t group_mark);

    Status save_param_to_device(void);


    wxDECLARE_EVENT_TABLE();
};

#endif // __COMMANDPROCESS_H__
